package org.googlecode.viewt.core.tools.formbean;

import org.apache.velocity.VelocityContext;
import org.googlecode.viewt.core.tools.AbstractVelocityGenerator;
import org.googlecode.viewt.core.tools.formbean.types.FormBeanDef;
import org.googlecode.viewt.core.tools.formbean.types.FormBeans;
import org.googlecode.viewt.core.tools.po.POConfigRepository;
import org.googlecode.viewt.core.tools.po.POConfigUtil;

public abstract class BaseFormBeanGenerator extends AbstractVelocityGenerator {
	public static final String CONTEXT_PROP_REPOSITORY = "REPOSITORY";
	public static final String CONTEXT_PROP_POREPOSITORY = "POREPOSITORY";
	public static final String CONTEXT_PROP_UTIL = "UTILITY";
	public static final String CONTEXT_PROP_POUTIL = "POUTILITY";
	public static final String CONTEXT_PROP_GENERATOR = "GENERATOR";
	public static final String CONTEXT_PROP_PRJNAME = "PROJECT";
	public static final String CONTEXT_PROP_MODNAME = "MODULE";
	public static final String CONTEXT_PROP_CURFORMBEANDEF = "CURRENTFORMBEAN";
	private FormBeanCfgRepository formbeanRepository;
	private POConfigRepository poRepository;
	private String destPath;
	private String fileTemplatePath;

	public BaseFormBeanGenerator() {
		this.formbeanRepository = null;

		this.poRepository = null;

		this.destPath = null;

		this.fileTemplatePath = null;
	}

	public void init(FormBeanCfgRepository formbeanRepository, String destPath)
			throws Exception {
		super.init();
		setRepository(formbeanRepository);
		setDestPath(destPath);
	}

	public void performGen() throws Exception {
		if ((this.formbeanRepository == null) || (this.destPath == null)) {
			getLogger()
					.error(
							"Perform generation fail, set config and destination first");
			throw new Exception("config or enviroment not set");
		}

		VelocityContext context = getContext();
		if (null == context) {
			context = new VelocityContext();
			setContext(context);
		}
		context.put("REPOSITORY", this.formbeanRepository);
		context.put("POREPOSITORY", this.poRepository);
		context.put("UTILITY", new FormBeanUtil());
		context.put("POUTILITY", new POConfigUtil());
		context.put("GENERATOR", this);
		context.put("PROJECT", this.formbeanRepository.getProjectName());
		context.put("MODULE", this.formbeanRepository.getModuleName());

		setupContext();

		FormBeans formbeans = this.formbeanRepository.getMainDef();
		FormBeanDef[] formbeanDefs = formbeans.getFormBeanDef();
		for (int i = 0; i < formbeanDefs.length; ++i) {
			FormBeanDef formbeanDef = formbeanDefs[i];
			String className = formbeanDef.getClassName();

			if (needGenerate(className)) {
				String templateName = getTemplate(className);
				String outputFile = getOutputFile(className);
				if ((null == templateName) || ("".equals(templateName))) {
					getLogger().error(
							"Empty template name:" + templateName
									+ ", generation fail");
					throw new Exception("Can not get template for formbean:"
							+ className);
				}
				if ((null == outputFile) || ("".equals(outputFile))) {
					getLogger().error(
							"Empty output file:" + outputFile
									+ ", generation fail");
					throw new Exception("Can not get output file for formbean:"
							+ className);
				}
				context.put("CURRENTFORMBEAN", formbeanDef);

				setupContext(className);

				singleOutput(templateName, outputFile);

				cleanContext(className);

				context.remove("CURRENTFORMBEAN");

				getLogger().debug(
						"generate code for class:" + className + " succeed");
			} else {
				getLogger().debug(
						"need not generate code for class:" + className
								+ ", bypass");
			}

		}

		cleanContext();

		context.remove("MODULE");
		context.remove("PROJECT");
		context.remove("GENERATOR");
		context.remove("POUTILITY");
		context.remove("UTILITY");
		context.remove("POREPOSITORY");
		context.remove("REPOSITORY");

		getLogger().debug("Perform code generation done.");
	}

	public void setRepository(FormBeanCfgRepository formbeanRepository) {
		this.formbeanRepository = formbeanRepository;
	}

	public FormBeanCfgRepository getRepository() {
		return this.formbeanRepository;
	}

	public void setPORepository(POConfigRepository poRepository) {
		this.poRepository = poRepository;
	}

	public POConfigRepository getPORepository() {
		return this.poRepository;
	}

	public void setDestPath(String destPath) {
		this.destPath = destPath;
	}

	public String getDestPath() {
		return this.destPath;
	}

	public void setFileTemplatePath(String fileTemplatePath) {
		this.fileTemplatePath = fileTemplatePath;
	}

	public String getFileTemplatePath() {
		return this.fileTemplatePath;
	}

	public String getPackageTemplatePath() {
		return "resource/template/formbean";
	}

	public abstract String getTemplate(String paramString) throws Exception;

	public abstract String getOutputFile(String paramString) throws Exception;

	public abstract boolean needGenerate(String paramString) throws Exception;

	public abstract void setupContext() throws Exception;

	public abstract void setupContext(String paramString) throws Exception;

	public abstract void cleanContext(String paramString) throws Exception;

	public abstract void cleanContext() throws Exception;
}